﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// NotReviewedButNeeded
#pragma once
#include "GcmpDatabase.h"
#include "GbmpCommon.h"
#include "ClassId.h"
#include "NdbPropertySchema.h"
#include <sstream>

namespace gcmp
{
    struct NdbElementExportOrCompareOptions;
    class INdbObjectMemoryModelNodeVisitor;

    /// \brief NdbObjectMemoryModelNode类型
    enum class NdbObjectMemoryModelNodeType : int32_t
    {
        Unknown = -1,        /// < 未知
        Group = 0,          /// < 组
        Leaf = 1,           /// < 叶子
        Fixed = 2,          /// < 固定长度
        Fixed8Bits = 3,     /// < 固定长度:8Bits
        Fixed16Bits = 4,    /// < 固定长度:16Bits
        Fixed32Bits = 5,    /// < 固定长度:32Bits
        Fixed64Bits = 6,    /// < 固定长度:64Bits
        FixedDouble = 7,    /// < 固定长度:Double
        FixedFloat = 8,     /// < 固定长度:Float
    };

    //////////////////////////////////////////////////////////////////////////
    /// \brief 节点标记枚举
    enum NdbObjectMemoryModelNodeStatusMarkFlag : UInt16
    {
        None = 0,               /// < 无标记
        Added = 1 << 0,         /// < 新增
        ToBeRemoved = 1 << 1,   /// < 即将被删除。拷贝时忽略此节点
    };

    class GCMP_DATABASE_EXPORT NdbObjectMemoryModelNode
    {
        DEFINE_CAST_BASE(gcmp::NdbObjectMemoryModelNode)
    public:
        NdbObjectMemoryModelNode() noexcept = default;

        ~ NdbObjectMemoryModelNode() noexcept = default;

        NdbObjectMemoryModelNode(NdbObjectMemoryModelNode&& another) noexcept = default;

        NdbObjectMemoryModelNode& operator = (NdbObjectMemoryModelNode&& another) noexcept = default;

        NdbObjectMemoryModelNode(const NdbObjectMemoryModelNode& another) noexcept;

        NdbObjectMemoryModelNode& operator = (const NdbObjectMemoryModelNode& another) noexcept;

        NdbObjectMemoryModelNode(const ClassId& classId, UInt32 version) noexcept
            : m_classId(classId)
            , m_version(version)
        {}

        const std::wstring& GetName() const;

        void SetName(const std::wstring& name);

        const UInt32 GetVersion() const { return m_version; }
        void SetVersion(UInt32 version) { m_version = (UInt16)version; }

        NdbPropertySchemaType GetSchemaType() const { return m_schemaType; }
        void SetSchemaType(NdbPropertySchemaType schemaType) { m_schemaType = schemaType; }

        const ClassId & GetClassId() const { return m_classId; }
        void SetClassId(const ClassId & classId) { m_classId = classId; }

        bool IsMarkedAsAdded () const { return 0 != (NdbObjectMemoryModelNodeStatusMarkFlag::Added & m_markFlags); }

        void MarkAsAdded(bool flag)
        {
            if (flag)
            {
                m_markFlags |= NdbObjectMemoryModelNodeStatusMarkFlag::Added;
            }
            else
            {
                m_markFlags &= ~NdbObjectMemoryModelNodeStatusMarkFlag::Added;
            }
        }

        bool IsMarkedAsToBeRemoved() const { return 0 != (NdbObjectMemoryModelNodeStatusMarkFlag::ToBeRemoved & m_markFlags); }

        void MarkAsToBeRemoved(bool flag)
        {
            if (flag)
            {
                m_markFlags |= NdbObjectMemoryModelNodeStatusMarkFlag::ToBeRemoved;
            }
            else
            {
                m_markFlags &= ~NdbObjectMemoryModelNodeStatusMarkFlag::ToBeRemoved;
            }
        }

        virtual NdbObjectMemoryModelNodeType GetType() const = 0;

        virtual bool IsLeaf() const = 0;

        virtual UInt64 GetDataSize() const = 0;

        virtual const void * GetData() const = 0;

        virtual void * GetDataForWrite() = 0;

        /// \brief 接受访问
        /// \param visitor 访问者
        virtual void Accept(INdbObjectMemoryModelNodeVisitor * visitor) = 0;

        // 对比两个节点是否相同，返回值指示是否继续比较。
        virtual bool Compare(
            const NdbObjectMemoryModelNode & base,                                  // 基准节点
            const std::vector<std::pair<std::wstring, std::wstring>> & attributes,  // 节点的属性信息，外部传入。比如是父对象，还是属性对象，还是顶层对象。
            const NdbElementExportOrCompareOptions & options,                       // 比较控制选项，包括输出路径、是否忽略无序容器顺序等等
            int level,                                                              // 控制打印缩进
            bool & areEqual,                                                        // 是否相等
            bool reportNotEqual,                                                    // 不相等且reportNotEqual为true时，具体信息在woss
            std::wostringstream & woss                                              // 输出流
        ) const;

    protected:
        std::unique_ptr<std::wstring>   m_name;
        ClassId                         m_classId;
        UInt16                          m_version = 0;
        UInt8                           m_markFlags = 0;                                // 标记枚举的复合值
        NdbPropertySchemaType           m_schemaType = NdbPropertySchemaType::Invalid;
    };
}
